package com.xbongbong.saas.help;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.jxc.help.DataBackFillHelp;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.ext.OptionalRangeEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.enums.SheetTypeEnum;
import com.xbongbong.paas.field.DefaultAttrPoJo;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.ProSaveHelp;
import com.xbongbong.paas.model.PaasAppModel;
import com.xbongbong.paas.pojo.dto.ValidateDataDTO;
import com.xbongbong.paas.pojo.vo.FormDataUpdateGetVO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.InvoiceRelationshipEntity;
import com.xbongbong.saas.domain.entity.PayBalanceEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.domain.entity.ProductCategoryEntity;
import com.xbongbong.saas.domain.entity.PurchaseInvoiceRelationshipEntity;
import com.xbongbong.saas.domain.entity.UserTeamEntity;
import com.xbongbong.saas.domain.entity.ext.PayPlanSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.enums.RedundantTemplateTypeEnum;
import com.xbongbong.saas.enums.RelativeProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.InvoiceEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.dictionary.InventoryStatusEnum;
import com.xbongbong.saas.enums.dictionary.TransferStatusEnum;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.PayBalanceModel;
import com.xbongbong.saas.model.PayPlanSheetModel;
import com.xbongbong.saas.model.PaymentBalanceModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.ProductCategoryModel;
import com.xbongbong.saas.service.toolbox.help.AttrDecimalPrecisionHelper;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.UserEntity;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getIntegerOrDefaultFromFormData;


/**
 * @author haibing.zhang
 * @version v1.0
 * @date 2019/1/16
 * @since v1.0
 */
@Component
public class SaasUpdateHelp extends BaseHelp {

    private static final Logger LOG = LoggerFactory.getLogger(SaasUpdateHelp.class);

    @Resource
    private ProductCategoryModel productCategoryModel;
    @Resource
    private PaasAppModel paasAppModel;
    @Resource
    private PaymentBalanceModel paymentBalanceModel;
    @Resource
    private DataBackFillHelp dataBackFillHelp;
    @Resource
    private SaasSaveHelp saasSaveHelp;
    @Resource
    private PayBalanceModel payBalanceModel;
    @Resource
    private DefaultAttrHelp defaultAttrHelp;
    @Resource
    private FundHelp fundHelp;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PayPlanSheetModel payPlanSheetModel;
    @Resource
    private IndexTypeModel indexTypeModel;

    /**
     * 编辑时saas特殊返回字段，放在一个对象中
     *
     * @param formDataUpdateGetVO
     * @param businessType
     * @author chaoxiong.lei
     * @Date 15:26 2019/2/18
     * @since
     * @return void
     **/
    public void formatSaasAttrToReturn(FormDataUpdateGetVO formDataUpdateGetVO, Integer businessType, JSONObject data) throws XbbException {
        if (formDataUpdateGetVO == null || businessType == null) {
            return;
        }
        RedundantTemplateTypeEnum templateTypeEnum = RedundantTemplateTypeEnum.getByCode(businessType);
        JSONObject saasReturnObj = new JSONObject();
        List<FieldAttrEntity> explainList = formDataUpdateGetVO.getExplainList();
        switch (templateTypeEnum) {
            case PRODUCT:
                // TODO 是否启用进销存
                String corpid = formDataUpdateGetVO.getPaasFormEntity().getCorpid();
                Boolean enableJxc = paasAppModel.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);
                saasReturnObj.put("isJxcUse", enableJxc);
                formDataUpdateGetVO.setSaasObj(saasReturnObj);
                break;
            case INVENTORY:
                boolean hasOutOrin = false;
                Integer status = getIntegerOrDefaultFromFormData(data, InventoryEnum.STATUS.getAttr(), BasicConstant.ZERO);
                if (status.equals(InventoryStatusEnum.ALREADY_OUT_INSTOCK.getCode())) {
                    hasOutOrin = true;
                }
                if (hasOutOrin) {
                    explainList.forEach(item -> {
                        if (Objects.equals(item.getAttr(), InventoryEnum.WAREHOUSE_ID.getAttr())) {
                            item.setEditable(BasicConstant.ZERO);
                        }
                    });
                }
                break;
            case TRANSFER:
                hasOutOrin = false;
                Integer transferStatus = getIntegerOrDefaultFromFormData(data, TransferEnum.STATUS.getAttr(), BasicConstant.ZERO);
                if (transferStatus.equals(TransferStatusEnum.ALREADY_OUT_INSTOCK.getCode())) {
                    hasOutOrin = true;
                }
                if (hasOutOrin) {
                    explainList.forEach(item -> {
                        if (Objects.equals(item.getAttr(), TransferEnum.OUT_WAREHOUSE_ID.getAttr()) || Objects.equals(item.getAttr(), TransferEnum.INTO_WAREHOUSE_ID.getAttr())) {
                            item.setEditable(BasicConstant.ZERO);
                        }
                    });
                }
                break;
            default:
                break;
        }
    }

    /**
     * 获取用户类型类型的数据
     *
     * @param data 表单数据
     * @param userMap 用户容器
     * @param attr 要获取数据的key值
     * @throws XbbException 类型转换失败异常
     * @author chaoxiong.lei
     * @date 14:09 2019/1/23
     * @since v1.0
     **/
    public String getUserOrDefaultFromFormData(JSONObject data, Map<String, UserEntity> userMap, String attr, String defaultValue) throws XbbException {
        String stringFromFormData = FastJsonHelper.getStringFromFormData(data, attr);
        UserEntity userEntity = userMap.get(stringFromFormData);
        if (Objects.isNull(stringFromFormData) || Objects.isNull(userEntity)) {
            stringFromFormData = defaultValue;
        } else {
            stringFromFormData = userEntity.getName();
        }
        return stringFromFormData;
    }

    /**
     * 获取Double类型的数据,忽略异常
     *
     * @param data 表单数据
     * @param attr 要获取数据的key值
     * @throws XbbException 类型转换失败异常
     * @author feng.zheng
     * @Date 14:09 2019/1/23
     * @since v1.0
     **/
    public Double getDoubleIgnoreExceptionFormData(JSONObject data, String attr, Double defaultValue) {
        Double doubleFromFormData = null;
        try {
            doubleFromFormData = getDoubleFromFormData(data, attr);
        } catch (XbbException e) {
            doubleFromFormData = null;
        }
        if (Objects.isNull(doubleFromFormData)) {
            doubleFromFormData = defaultValue;
        }
        return doubleFromFormData;
    }

    /**
     * Description: 获取照片url集合
     * 返回可能为null，获取之后需要进行非null判断
     * @param data
     * @param attr
     * @return list
     * @throws XbbException
     * @author 刘阳
     * @date 2019/7/3 3:55 PM
     * @since v1.0
     */
    public List<Object> getListFromFormData(JSONObject data, String attr) throws XbbException {
        List<Object> photoList = new ArrayList<>();
        if (data == null || attr == null) {
            return photoList;
        }
        try {
            if (data.get(attr) == null) {
                return photoList;
            }
            JSONArray photoArray = data.getJSONArray(attr);
            for (Object obj : photoArray) {
                String tel = obj.toString();
                photoList.add(tel);
            }
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
        return photoList;
    }

    /**
     * 设置JSONArray类型的数据
     *
     * @param data  表单数据
     * @param attr  要设置数据的key值
     * @param value 要设置数据的value值
     * @throws XbbException 类型转换失败异常
     * @author chaoxiong.lei
     * @Date 14:09 2019/1/23
     * @since v1.0
     **/
    public void setJSONArrayIntoFormData(JSONObject data, String attr, JSONArray value) throws XbbException {
        if (data == null || attr == null || value == null) {
            return;
        }
        try {
            // 保证原来的值是JSONArray类型的，否则不允许插入
            JSONArray attrValue = data.getJSONArray(attr);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
        data.put(attr, value);
    }

    /**
     * 获取Long类型的数据,否则就是默认值，不抛错
     *
     * @param data 表单数据
     * @param attr 要获取数据的key值
     * @param defaultValue 默认值
     * @author long.rao
     * @date 2019-10-17 15:25
     **/
    public Long eitherLongOrTheDefault(JSONObject data, String attr, Long defaultValue){
        if (data == null || attr == null) {
            return defaultValue;
        }
        try {
            if (data.get(attr) == null) {
                return defaultValue;
            }
            return data.getLong(attr);
        } catch (Exception e) {
            return defaultValue;
        }
    }

    /**
     * 设置Long类型的数据
     *
     * @param data  表单数据
     * @param attr  要设置数据的key值
     * @param value 要设置数据的value值
     * @throws XbbException 类型转换失败异常
     * @author chaoxiong.lei
     * @Date 14:09 2019/1/23
     * @since v1.0
     **/
    public void setLongIntoFormData(JSONObject data, String attr, Long value) throws XbbException {
        if (data == null || attr == null || value == null) {
            return;
        }
        try {
            // 保证原来的值是String类型的，否则不允许插入
            Long attrValue = data.getLong(attr);
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
        data.put(attr, value);
    }

    /**
     * 格式化选择产品控件返回给前端
     *
     * @param relativeProductEnum 产品字段枚举
     * @param value 要回显的值
     * @param fieldAttrEntity 从数据库获取的字段解释实体
     * @author chaoxiong.lei
     * @date 18:37 2019/2/25
     * @since v1.0
     **/
    public JSONObject formatSelectProduct4Show(RelativeProductEnum relativeProductEnum, Object value, FieldAttrEntity fieldAttrEntity) {
        if (fieldAttrEntity != null) {
            Integer visible = fieldAttrEntity.getVisible();
            Integer isOpen = fieldAttrEntity.getIsOpen();
            if (Objects.equals(visible, 0) || Objects.equals(isOpen, 0)) {
                return null;
            }
        }

        String saasAttr = relativeProductEnum.getSaasAttr();
        if (Objects.equals(relativeProductEnum, RelativeProductEnum.COST)) {
            // 成本的saasAttr是productCost
            saasAttr = StringConstant.PRODUCT_COST;
        }

        value = value == null ? "" : value;
        if (value instanceof JSONObject) {
            JSONObject jsonObject = (JSONObject) value;
            value = jsonObject.isEmpty() ? "" : value;
        }

        Integer accuracy = null;
        if (fieldAttrEntity != null) {
            accuracy = fieldAttrEntity.getAccuracy();
        }
        if(Objects.equals(relativeProductEnum, RelativeProductEnum.SALE_DISCOUNT) || Objects.equals(relativeProductEnum, RelativeProductEnum.ATTRITION_RATE)) {
            accuracy = AttrDecimalPrecisionHelper.DEFAULT_PRECISION;
        }
        if (Objects.equals(relativeProductEnum, RelativeProductEnum.COST)) {
            accuracy = accuracy == null ? AttrDecimalPrecisionHelper.DEFAULT_PRECISION : accuracy;
            double costValue = StringUtil.toDouble(Objects.toString(value), 0D);
            costValue = Arith.round(costValue, accuracy);
            value = Objects.toString(costValue, "");
        }

        JSONObject dataObj = new JSONObject();
        dataObj.put("attr", saasAttr);
        dataObj.put("attrValue", value);
        dataObj.put("attrName", relativeProductEnum.getAttrName());
        dataObj.put("fieldType", relativeProductEnum.getFieldType());
        dataObj.put("isRedundant", relativeProductEnum.getIsRedundant());
        // 是否可编辑默认使用枚举中默认的值，需要特殊处理的在外层修改
        dataObj.put("editable", relativeProductEnum.getEditable());
        dataObj.put("accuracy", accuracy);
        if (fieldAttrEntity != null) {
            // 是否必填要实时获取
            dataObj.put("required", fieldAttrEntity.getRequired());
        }

        return dataObj;
    }


    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = defaultAttrHelp.packegeLinkBusinessJsonArray(dataId, name);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name, Long formId) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        jsonObject.put(StringConstant.FORM_ID, formId);
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(Object defaultValue) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        defaultAttrPoJo.setLinkFormValue(defaultValue);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name, Integer businessType) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        jsonObject.put(StringConstant.BUSINESS_TYPE, businessType);
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultLinkPojo(Long dataId, String name, Integer businessType) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        jsonObject.put(StringConstant.BUSINESS_TYPE, businessType);
        defaultAttrPoJo.setLinkFormValue(jsonObject);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name, String attr, Object value) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        jsonObject.put(attr, value);
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name,Map<String,Object> attrMap) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        Iterator<Map.Entry<String,Object>> it = attrMap.entrySet().iterator();
        while (it.hasNext()){
            Map.Entry<String,Object> map = it.next();
            jsonObject.put(map.getKey(),map.getValue());
        }
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo getDefaultAttrPojo(JSONArray jsonArray) {
        return DefaultAttrHelp.getDefaultAttrPojo(jsonArray);
    }

    public DefaultAttrPoJo setDefaultValue(Object defaultValue) {
        return DefaultAttrHelp.setDefaultValue(defaultValue);
    }

    public DefaultAttrPoJo setUserDefaultValue(List<UserTeamEntity> userTeamEntities) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        defaultAttrPoJo.setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
        List<OptionalRangeEntity> defaultList = new ArrayList<>(userTeamEntities.size());
        for (UserTeamEntity entity : userTeamEntities) {
            OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
            optionalRangeEntity.setId(entity.getUserId());
            optionalRangeEntity.setName(entity.getUserName());
            optionalRangeEntity.setUserAvatar(entity.getUserAvatar());
            defaultList.add(optionalRangeEntity);
        }
        defaultAttrPoJo.setDefaultList(defaultList);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo setDefaultValue(String defaultValue) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        defaultAttrPoJo.setDefaultValue(defaultValue);
        defaultAttrPoJo.setDefaultType(StringConstant.CUSTOM);
        return defaultAttrPoJo;
    }

    public DefaultAttrPoJo setDeptDefaultAttrPoJo(String deptId, String deptName) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        List<OptionalRangeEntity> defaultList = new ArrayList<>();
        OptionalRangeEntity optionalRangeEntity = new OptionalRangeEntity();
        optionalRangeEntity.setProperty(OptionalRangeEnum.DEPT.getValue());
        optionalRangeEntity.setId(deptId);
        optionalRangeEntity.setName(deptName);
        optionalRangeEntity.setEditable(BasicConstant.ONE);
        defaultList.add(optionalRangeEntity);
        defaultAttrPoJo.setDefaultType(StringConstant.CUSTOM);
        defaultAttrPoJo.setDefaultList(defaultList);
        return defaultAttrPoJo;
    }

    /**
     * 解析分类数据，存放分类名称
     * @author 吴峰
     * @date 2019/4/17 10:51
     * @param result 数据
     * @param attr 字段索引
     * @param corpid 公司id
     * @return void
     * @throws XbbException 业务异常
     */
    public void formatCategoryId4ShowName(JSONObject result, String attr, String corpid) throws XbbException {
        Long categoryId = FastJsonHelper.getLongOrDefaultFromFormData(result, attr, null);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID, corpid);
        param.put(StringConstant.DEL, DelEnum.NORMAL.getDel());
        ProductCategoryEntity  productCategoryEntity = productCategoryModel.getByKey(categoryId, corpid);
        if (Objects.nonNull(productCategoryEntity)  && Objects.nonNull(categoryId)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("id", categoryId);
            jsonObject.put("value", productCategoryEntity.getName());
            result.put(attr, jsonObject);
        }
    }

    public void getInvoiceRefMap(Map<Long,Double> contractMap,Map<Long,Double> paymentRefMap,Map<Long,Double> paymentSheetRefMap,List<InvoiceRelationshipEntity> invoiceRelationshipEntityList,Set<Long> contractIds,Set<Long> paymentIds,Set<Long> paymentSheetIds){
        //invoiceRelationshipEntityList.forEach(invoiceRelationshipEntity -> {
        if(CollectionsUtil.isNotEmpty(invoiceRelationshipEntityList)) {
            for (int i = 0; i < invoiceRelationshipEntityList.size(); i++) {
                InvoiceRelationshipEntity invoiceRelationshipEntity = invoiceRelationshipEntityList.get(i);
                if (!Objects.equals(invoiceRelationshipEntity.getContractId().intValue(), BasicConstant.ZERO)) {
                    if (contractMap.containsKey(invoiceRelationshipEntity.getContractId())) {
                        contractMap.put(invoiceRelationshipEntity.getContractId(), contractMap.get(invoiceRelationshipEntity.getContractId()) + invoiceRelationshipEntity.getMoney());
                    } else {
                        contractMap.put(invoiceRelationshipEntity.getContractId(), invoiceRelationshipEntity.getMoney());
                    }
                    if (contractIds != null) {
                        contractIds.add(invoiceRelationshipEntity.getContractId());
                    }
                }
                if (!Objects.equals(invoiceRelationshipEntity.getPaymentId().intValue(), BasicConstant.ZERO) &&
                        !Objects.equals(invoiceRelationshipEntity.getContractId().intValue(), BasicConstant.ZERO)) {
                    if (paymentRefMap.containsKey(invoiceRelationshipEntity.getPaymentId())) {
                        paymentRefMap.put(invoiceRelationshipEntity.getPaymentId(), paymentRefMap.get(invoiceRelationshipEntity.getPaymentId()) + invoiceRelationshipEntity.getMoney());
                    } else {
                        paymentRefMap.put(invoiceRelationshipEntity.getPaymentId(), invoiceRelationshipEntity.getMoney());
                    }
                    if (paymentIds != null) {
                        paymentIds.add(invoiceRelationshipEntity.getPaymentId());
                    }
                } else if (!Objects.equals(invoiceRelationshipEntity.getPaymentSheetId().intValue(), BasicConstant.ZERO)) {
                    if (paymentSheetRefMap.containsKey(invoiceRelationshipEntity.getPaymentSheetId())) {
                        paymentSheetRefMap.put(invoiceRelationshipEntity.getPaymentSheetId(), paymentSheetRefMap.get(invoiceRelationshipEntity.getPaymentSheetId()) + invoiceRelationshipEntity.getMoney());
                    } else {
                        paymentSheetRefMap.put(invoiceRelationshipEntity.getPaymentSheetId(), invoiceRelationshipEntity.getMoney());
                    }
                    if (paymentSheetIds != null) {
                        paymentSheetIds.add(invoiceRelationshipEntity.getPaymentSheetId());
                    }
                }
            }
        }
    }

    public void getPurchaseInvoiceRefMap(Map<Long,Double> purchaseMap, Map<Long,Double> payPlanRefMap, Map<Long,Double> paySheetRefMap, List<PurchaseInvoiceRelationshipEntity> purchaseInvoiceRelationshipEntityList, Set<Long> purchaseIds, Set<Long> payPlanIds, Set<Long> paySheetIds){
        if(CollectionsUtil.isNotEmpty(purchaseInvoiceRelationshipEntityList)) {
            for (int i = 0; i < purchaseInvoiceRelationshipEntityList.size(); i++) {
                PurchaseInvoiceRelationshipEntity purchaseInvoiceRelationshipEntity = purchaseInvoiceRelationshipEntityList.get(i);
                if (!Objects.equals(purchaseInvoiceRelationshipEntity.getPurchaseId().intValue(), BasicConstant.ZERO)) {
                    if (purchaseMap.containsKey(purchaseInvoiceRelationshipEntity.getPurchaseId())) {
                        purchaseMap.put(purchaseInvoiceRelationshipEntity.getPurchaseId(),purchaseMap.get(purchaseInvoiceRelationshipEntity.getPurchaseId()) + purchaseInvoiceRelationshipEntity.getMoney());
                    } else {
                        purchaseMap.put(purchaseInvoiceRelationshipEntity.getPurchaseId(), purchaseInvoiceRelationshipEntity.getMoney());
                    }
                    if (purchaseIds != null) {
                        purchaseIds.add(purchaseInvoiceRelationshipEntity.getPurchaseId());
                    }
                }
                if (!Objects.equals(purchaseInvoiceRelationshipEntity.getPayPlanId().intValue(), BasicConstant.ZERO) &&
                        !Objects.equals(purchaseInvoiceRelationshipEntity.getPurchaseId().intValue(), BasicConstant.ZERO)) {
                    if (payPlanRefMap.containsKey(purchaseInvoiceRelationshipEntity.getPayPlanId())) {
                        payPlanRefMap.put(purchaseInvoiceRelationshipEntity.getPayPlanId(), payPlanRefMap.get(purchaseInvoiceRelationshipEntity.getPayPlanId()) + purchaseInvoiceRelationshipEntity.getMoney());
                    } else {
                        payPlanRefMap.put(purchaseInvoiceRelationshipEntity.getPayPlanId(), purchaseInvoiceRelationshipEntity.getMoney());
                    }
                    if (payPlanIds != null) {
                        payPlanIds.add(purchaseInvoiceRelationshipEntity.getPayPlanId());
                    }
                } else if (!Objects.equals(purchaseInvoiceRelationshipEntity.getPaySheetId().intValue(), BasicConstant.ZERO)) {
                    if (paySheetRefMap.containsKey(purchaseInvoiceRelationshipEntity.getPaySheetId())) {
                        paySheetRefMap.put(purchaseInvoiceRelationshipEntity.getPaySheetId(), paySheetRefMap.get(purchaseInvoiceRelationshipEntity.getPaySheetId()) + purchaseInvoiceRelationshipEntity.getMoney());
                    } else {
                        paySheetRefMap.put(purchaseInvoiceRelationshipEntity.getPaySheetId(), purchaseInvoiceRelationshipEntity.getMoney());
                    }
                    if (paySheetIds != null) {
                        paySheetIds.add(purchaseInvoiceRelationshipEntity.getPaySheetId());
                    }
                }
            }
        }
    }

    public void getOldInvoiceRefMap(Map<Long,Double> contractMap, Map<Long,Double> paymentRefMap, Map<Long,Double> paymentSheetRefMap, List<PaasFormDataEntityExt> oldRedInvoiceList,Map<Long,Double> contractAmountMap,Map<Long,Double> paymentAmountMap,Map<Long,Double> paymentSheetAmountMap,Long invoiceId) throws XbbException{
        //老数据可能会混入没有红冲过的新数据,这个会再之前分配新老数据时会过滤掉
        if(CollectionsUtil.isNotEmpty(oldRedInvoiceList)) {
            PaasFormDataEntityExt paasFormDataEntityExt = null;
            for(PaasFormDataEntityExt paasFormExt : oldRedInvoiceList){
                if(Objects.equals(paasFormExt.getId(),invoiceId)){
                    paasFormDataEntityExt = paasFormExt;
                    break;
                }
            }
            if(Objects.nonNull(paasFormDataEntityExt)) {
                JSONObject data = paasFormDataEntityExt.getData();
                if (Objects.nonNull(data.getJSONArray(InvoiceEnum.CONTRACT_ID.getAttr()))) {
                    JSONArray array = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, InvoiceEnum.CONTRACT_ID.getAttr(), new JSONArray());
                    saasSaveHelp.getOldInvoiceAmount(array, contractMap, contractAmountMap, data);
                }
                if (Objects.nonNull(data.getJSONArray(InvoiceEnum.PAYMENT_ID.getAttr()))) {
                    JSONArray array = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, InvoiceEnum.PAYMENT_ID.getAttr(), new JSONArray());
                    saasSaveHelp.getOldInvoiceAmount(array, paymentRefMap, paymentAmountMap, data);
                }
                if (Objects.nonNull(data.getJSONArray(InvoiceEnum.PAYMENT_SHEET_ID.getAttr()))) {
                    JSONArray array = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, InvoiceEnum.PAYMENT_SHEET_ID.getAttr(), new JSONArray());
                    saasSaveHelp.getOldInvoiceAmount(array, paymentSheetRefMap, paymentSheetAmountMap, data);
                }
            }
        }
    }

        /**
         * 得到amountDetail，目前只有回款单和发票有该金额明细
         * @param dataList 前端请求数据dataList
         * @throws XbbException
         * @author 伟强
         * @date 19/11/15 020 14:47
         * @update 19/11/20 020 14:47 by zcp 兼容发票的amountDetail处理
         * @since v1.0
         * @version v1.0
         */
    public JSONArray getAmountDetail(JSONObject dataList) throws XbbException {
        return FastJsonHelper.getAmountDetail(dataList);
    }

    /**
     * 封装关联客户id和name到json数组
     *
     * @param dataId
     * @param name
     * @return
     */
    public JSONArray packegeLinkBusinessJsonArray(Long dataId, String name, String corpid,XbbRefTypeEnum xbbRefTypeEnum, XbbRefTypeEnum linkXbbRefTypeEnum) {
        Double advancePaymentBalance = 0D;
        try {
            switch (xbbRefTypeEnum) {
                case CUSTOMER_MANAGEMENT:
                    PaymentBalanceEntity paymentBalanceEntity = paymentBalanceModel.getByCustomerId(dataId,corpid);
                    if ( Objects.nonNull(paymentBalanceEntity) ){
                        advancePaymentBalance = paymentBalanceEntity.getAdvancePaymentBalance();
                    }
                    break;
                case SUPPLIER:
                    PayBalanceEntity payBalanceEntity = payBalanceModel.getBySupplierId(dataId,corpid);
                    if ( Objects.nonNull(payBalanceEntity) ){
                        advancePaymentBalance = payBalanceEntity.getAdvancePayBalance();
                    }
                    break;
                default:
                    break;
            }

        } catch (XbbException e) {
            LOG.error("获取客户可核销预收款错误", e);
            advancePaymentBalance = 0D;
        }
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, advancePaymentBalance);
        jsonArray.add(jsonObject);
        return jsonArray;
    }

    /**
     * 封装客户信息到defaultAttr,之前是不需要加可回款金额的
     * @param dataId
     * @param name
     * @param corpid
     * @return
     */
    public DefaultAttrPoJo getDefaultAttrPojo(Long dataId, String name, String corpid, XbbRefTypeEnum xbbRefTypeEnum, XbbRefTypeEnum linkXbbRefTypeEnum) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = packegeLinkBusinessJsonArray(dataId, name, corpid,xbbRefTypeEnum ,linkXbbRefTypeEnum);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    /**
     * 存在预收款余额时的数据封装
     * @param dataId ID
     * @param name 名称
     * @param paymentBalanceEntity 预收款实体
     * @return 封装结果
     * @author zhouwq
     * @date 2019/12/10 19:02
     */
    public DefaultAttrPoJo getDefaultAttrPojoByPaymentBalance(Long dataId, String name, PaymentBalanceEntity paymentBalanceEntity) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        if(paymentBalanceEntity != null) {
            jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, paymentBalanceEntity.getAdvancePaymentBalance());
        }
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    /**
     * 存在预收款余额时的数据封装
     * @param jsonArray 数组信息
     * @param paymentBalanceEntity 预收款实体
     * @return 封装结果
     * @author zhouwq
     * @date 2019/12/10 19:02
     */
    public DefaultAttrPoJo getDefaultAttrPojoByPaymentBalance(JSONArray jsonArray, PaymentBalanceEntity paymentBalanceEntity) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONObject jsonObject = jsonArray.getJSONObject(0);
        if(paymentBalanceEntity != null) {
            jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, paymentBalanceEntity.getAdvancePaymentBalance());
        }
        defaultAttrPoJo.setLinkFormValue(jsonArray);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    /**
     * 存在预付款余额时的数据封装
     * @param dataId ID
     * @param name 名称
     * @param balanceEntity 预付款实体
     * @return DefaultAttrPoJo
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public DefaultAttrPoJo getDefaultAttrPojoByPayBalance(Long dataId, String name, PayBalanceEntity balanceEntity) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONArray customerArr = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_ID, dataId);
        jsonObject.put(StringConstant.SAAS_LINK_BUSINESS_NAME, name);
        if(balanceEntity != null) {
            jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, balanceEntity.getAdvancePayBalance());
        }
        customerArr.add(jsonObject);
        defaultAttrPoJo.setLinkFormValue(customerArr);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    /**
     * 存在预付款余额时的数据封装
     * @param jsonArray 数组信息
     * @param payBalanceEntity 预付款实体
     * @return DefaultAttrPoJo
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public DefaultAttrPoJo getDefaultAttrPojoByPayBalance(JSONArray jsonArray, PayBalanceEntity payBalanceEntity) {
        DefaultAttrPoJo defaultAttrPoJo = new DefaultAttrPoJo();
        JSONObject jsonObject = jsonArray.getJSONObject(0);
        if(payBalanceEntity != null) {
            jsonObject.put(StringConstant.SAAS_LINK_ADVANCE_PAYMENT_BALANCE, payBalanceEntity.getAdvancePayBalance());
        }
        defaultAttrPoJo.setLinkFormValue(jsonArray);
        defaultAttrPoJo.setUseLinkValue(BasicConstant.ONE);
        return defaultAttrPoJo;
    }

    /**
     * JXC单据拆分旧数据编辑时新增字段回显
     * @param formData 数据
     * @param businessType 业务类型
     * @author JianTao.Xiong
     * @date 2019/12/11
     */
    public void formOldData(PaasFormDataEntityExt formData, Integer businessType) throws XbbException {
       dataBackFillHelp.formOldData(formData, businessType);
    }

    /**
     * 处理字段完成率，如现金毛利率、收款比例等
     * @param updateData 要更新的合同data
     * @param numerator 分子
     * @param denominator 分母
     * @param attr 字段
     * @author zcp
     * @date 19/12/6 006 22:28
     * @since v1.0
     * @version v1.0
     * @update 20/2/28 by zcp 从ContractServiceImpl移入
     */
    public void handleAttrPercent(JSONObject updateData, Double numerator, Double denominator, String attr) {
        if (Double.compare(denominator, BasicConstant.ZERO) == BasicConstant.ZERO) {
            updateData.put(attr, BasicConstant.ZERO);
        } else {
            updateData.put(attr, Arith.round(Arith.div(numerator, denominator), 4));
        }
    }
    /**
     * 更新父回/付款单时，同步更新子单
     * @param corpid 公司id
     * @param sheetTypeEnum 回款单类型
     * @param amountDetail 明细
     * @param explainMap 字段解释map
     * @param distributorMark 经销商标识
     * @return java.util.List<com.xbongbong.pro.domain.entity.UpdateDataEntity>
     * @throws XbbException
     * @author zcp
     * @since v1.0
     * @version v1.0
     */
    public List<UpdateDataEntity> updateSonDataList4Sheet(String corpid, SheetTypeEnum sheetTypeEnum, JSONArray amountDetail, Map<String, FieldAttrEntity> explainMap, Integer distributorMark) throws XbbException {
        if (CollectionsUtil.isEmpty(amountDetail) || amountDetail.size() <= BasicConstant.ONE) {
            return null;
        }
        Map<Long, JSONObject> idDataMap = new HashMap<>(amountDetail.size());
        List<Long> idIn = new ArrayList<>();
        for(Object obj : amountDetail){
            if (Objects.isNull(obj)) {
                continue;
            }
            JSONObject newData = (JSONObject)obj;
            Long dataId = newData.getLong(StringConstant.DATA_ID);
            if (Objects.isNull(dataId)) {
                continue;
            }
            //移除非data内字段
            fundHelp.removeNotInMapping(newData);
            idDataMap.put(dataId, newData);
            idIn.add(dataId);
        }
        if (idIn.size() <= BasicConstant.ONE) {
            return null;
        }
        List<PaasFormDataEntityExt> childList = new ArrayList<>();
        switch (sheetTypeEnum.getXbbRefTypeEnum()) {
            case PAYMENT_SHEET:
                List<PaymentSheetEntityExt> paymentsheetList = paymentSheetModel.getPaymentSheetByIdIn(corpid, idIn);
                childList.addAll(paymentsheetList);
                break;
            case PAY_SHEET:
                List<PayPlanSheetEntityExt> paysheetList = payPlanSheetModel.getPaySheetByIdIn(corpid, idIn);
                childList.addAll(paysheetList);
                break;
            default:
                break;
        }
        if (childList.size() <= BasicConstant.ZERO) {
            return null;
        }
        List<UpdateDataEntity> updateList = new ArrayList<>();
        ValidateDataDTO validateDataDTO = new ValidateDataDTO();
        validateDataDTO.setBusinessType(sheetTypeEnum.getBusinessType());
        validateDataDTO.setExplainMap(explainMap);
        validateDataDTO.setNonCheckAmount(true);
        for (PaasFormDataEntityExt entityExt : childList) {
            Long dataId = entityExt.getId();
            JSONObject newData = idDataMap.get(dataId);
            if (Objects.isNull(newData)) {
                continue;
            }
            validateDataDTO.setData(newData);
            //处理一些自定义字段的格式（非自定义的不能更改）
            ProSaveHelp.analyticalData(validateDataDTO);
            JSONObject oldData = JsonHelperUtil.getJSONObject(entityExt.getData());
            //处理得到最终的data（禁止编辑字段，要移除字段处理）
            JSONObject data = fundHelp.handlePaymentSheetData4Update(sheetTypeEnum, newData, oldData, distributorMark, null);
            Set<String> newKeySet = data.keySet();
            Set<String> oldKeySet = oldData.keySet();
            oldKeySet.removeAll(newKeySet);
            oldKeySet.forEach(removeKey -> {
                newData.put(removeKey, null);
            });
            UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(dataId, data, corpid);
            updateList.add(updateDataEntity);
        }
        return updateList;
    }
}

